package com.xc.controller;

import com.xc.SecurityUtil;
import com.xc.pojo.UserInfoBean;
import com.xc.util.AjaxResponse;
import com.xc.util.GlobalConfig;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 历史
 */
@RestController
@RequestMapping("/activitiHistory")
public class ActivitiHistoryController {

    @Autowired
    private HistoryService historyService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private SecurityUtil securityUtil;

    /**
     * 获取当前登录用户历史任务
     * @return
     */
    @GetMapping(value = "/getInstanceByUsername")
    public AjaxResponse getInstanceByUsername(@AuthenticationPrincipal UserInfoBean userInfoBean) {
        try{
            List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
                    .orderByHistoricTaskInstanceEndTime().desc()
                    .taskAssignee(userInfoBean.getUsername())
                    .list();

            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), list);
        }catch (Exception e){
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "获取当用户历史任务失败", e.toString());
        }
    }

    /**
     * 根据流程实例id查询任务
     * @param piID 程实例id
     * @return
     */
    @GetMapping(value = "/getInstanceBypiID")
    public AjaxResponse getInstanceBypiID(@RequestParam("taskId") String piID) {
        try{
            List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
                    .orderByHistoricTaskInstanceEndTime().desc()
                    .processInstanceId(piID)
                    .list();
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), null);
        }catch (Exception e){
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "根据流程实例" + piID + "查询任务失败", e.toString());
        }
    }

    /**
     * 高亮显示历史流程
     * @param instanceID 实例id
     * @param userInfoBean 当前登录用户
     * @return
     */
    @GetMapping("/getHighLine")
    public AjaxResponse getHighLine(@RequestParam("instanceID") String instanceID,@AuthenticationPrincipal UserInfoBean userInfoBean){
        try{
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(instanceID)
                    .singleResult();
            // ---- 1.读取 BPM
            BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
            Process process = bpmnModel.getProcesses().get(0);
            // 获取所有流程的 FlowElement 的 bpmn节点信息
            Collection<FlowElement> flowElements = process.getFlowElements();
            Map<String, String> map = new HashMap<>();
            for (FlowElement flowElement : flowElements){
                // 判断是否是线条
                if (flowElement instanceof SequenceFlow){
                    SequenceFlow sequenceFlow = (SequenceFlow) flowElement;
                    // 箭头的两端
                    String ref = sequenceFlow.getSourceRef();// 当前节点
                    String target = sequenceFlow.getTargetRef();// 目标节点
                    map.put(ref + target,sequenceFlow.getId());
                }
            }

            // ---- 2.获取全部历史流程节点
            List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
                    .processInstanceId(instanceID)
                    .list();
            // 各历史节点两两组合成key
            Set<String> keyList = new HashSet<>();
            for (HistoricActivityInstance i : list){
                for (HistoricActivityInstance j : list){
                    if (i != j){
                        keyList.add(i.getActivityId() + j.getActivityId());
                    }
                }
            }

            // ---- 3.高亮历史连线ID
            Set<String> highline = new HashSet<>();
            keyList.forEach(x -> highline.add(map.get(x)));

            // ---- 4.获取已经执行完成的节点
            List<HistoricActivityInstance> listFinished = historyService.createHistoricActivityInstanceQuery()
                    .processInstanceId(instanceID)
                    .finished()
                    .list();
            // 已经完成的节点高亮
            Set<String> highPoint = new HashSet<>();
            listFinished.forEach(x -> highPoint.add(x.getActivityId()));

            // ---- 5.获取待办节点
            List<HistoricActivityInstance> listUnFinished = historyService.createHistoricActivityInstanceQuery()
                    .processInstanceId(instanceID)
                    .unfinished()
                    .list();
            // 待办节点高亮
            Set<String> waitingPoint = new HashSet<>();
            listUnFinished.forEach(x -> waitingPoint.add(x.getActivityId()));

            // ---- 6.获取当前用户完成的任务
            String username = GlobalConfig.Test ? "bajie" : userInfoBean.getUsername();
            List<HistoricTaskInstance> taskInstanceList = historyService.createHistoricTaskInstanceQuery()
                    .processInstanceId(instanceID)
                    .taskAssignee(username)
                    .finished()
                    .list();
            // 我做过的节点高亮
            Set<String> iDo = new HashSet<>();
            taskInstanceList.forEach(x -> iDo.add(x.getTaskDefinitionKey()));

            // ---- 7.返回数据
            Map<String,Object> resultMap = new HashMap<>();
            resultMap.put("highline",highline);
            resultMap.put("highPoint",highPoint);
            resultMap.put("waitingPoint",waitingPoint);
            resultMap.put("iDo",iDo);

            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), resultMap);
        }catch (Exception e){
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "高亮历史任务失败", e.toString());
        }
    }
}
